import { Injectable } from '@nestjs/common';
const Redis = require("ioredis");

const { MongoClient } = require('mongodb');
const { nanoid } = require('nanoid')
const path = require('path')

const article_per_page = 8
const reply_first_page = 3
const reply_per_page = 10

const redis_client2 = new Redis({
    port: 6379, // Redis port
    host: "127.0.0.1", // Redis host
    db: 2,
});

@Injectable()
export class PostsService {

    mongoUrl: any = process.env.mongoUrl;
    db: any;
    constructor() {
        this.connect()
    }

    async connect() {
        this.db = await MongoClient.connect(this.mongoUrl, { useUnifiedTopology: true })
    }

    index(): any {
        //console.log(process.env)
        return "index page"
    }

    async page(pagenum: number, user_info) {
        const temp_page = Math.floor(+(pagenum))
        if (temp_page <= 0) {
            return { "status": 20000, "articles": [] }
        }
        if (temp_page > 1 && user_info == null) {
            return { "status": 30000, "articles": [], "info": "need to login" }
        }
        const dbo = this.db.db("forum");
        const article_list = await dbo.collection("posts").find({}).sort({ last_update: -1 }).skip(article_per_page * (temp_page - 1)).limit(article_per_page).toArray()
        return { "status": 20000, "articles": article_list }
    }

    async count() {
        const dbo = this.db.db("forum");
        const count = await dbo.collection("posts").countDocuments()
        return Math.ceil(count)
    }

    async viewPosts(pid: string) {
        const dbo = this.db.db("forum");
        const whereStr = {
            "pid": pid.toString()
        }
        const result = await dbo.collection("posts").findOne(whereStr)
        if (result) {
            return {
                "status": 20000,
                "raw": result.raw,
                "replys": result.replys,
                "data":result.last_update
                // "ticket_status": result.ticket_status
            }
        } else {
            return { "status": 40000, "info": JSON.stringify(result) }
        }
    }

    async PreviewPosts(pid: string) {
        let result = await redis_client2.hgetall(pid)
        //if not cached
        if (result.reply == null) {
            const dbo = this.db.db("forum");
            const temp = await dbo.collection("reply").find({ "pid": pid.toString() }).count()
            if (temp.length == 0) {
                return { "status": 40000, "info": JSON.stringify(result) }
            }
            await redis_client2.hmset(pid, "reply", temp * reply_per_page, "page", temp)
            result = {
                reply: temp * reply_per_page,
                page: temp
            }
        }
        if (result) {
            return {
                "status": 20000,
                "reply": result.reply,
                "page": result.page,
            }
        } else {
            return { "status": 40000, "info": JSON.stringify(result) }
        }
    }

    async viewReplyPage(pid: string, pagenum) {
        const dbo = this.db.db("forum");
        const result = await dbo.collection("reply").findOne({ "reply_page_id": pid.toString() + pagenum.toString() })
        // console.log(result)
        return { status: 20000, "reply": result }
    }

    async Addpost(user_info, post_json) {
        const dbo = this.db.db("forum");
        post_json["userId"] = user_info.userId.toString()
        post_json["date"] = new Date()
        // console.log(post_json)
        const pid = nanoid(16)
        //ticket_json["status"] = "created"
        await redis_client2.hmset(pid, "reply", 0, "page", 0)
        //mongodb
        const result = await dbo.collection("posts").insertOne({ "raw": post_json, "replys": [], "pid": pid, "userId": user_info.userId, "last_update": new Date(), "post_status": "created" })
        if (result.insertedCount) {
            return { "status": 20000, "pid": pid }
        } else {
            return { "status": 40000, "info": JSON.stringify(result) }
        }
    }

    async replyPost(pid: string, reply_json, userId: string) {
        reply_json["date"] = new Date()
        reply_json["userId"] = userId.toString()
        const dbo = this.db.db("forum");

        const redis_res = await redis_client2.hgetall(pid)
        if (redis_res == null) {
            return { "status": 40000, "info": JSON.stringify(redis_res) }
        } else {
            redis_res.page = +redis_res.page
            redis_res.reply = +redis_res.reply
        }
        // console.log(redis_res)
        let table: string, whereStr
        if (redis_res.reply < reply_first_page) {
            table = "posts"
            whereStr = {
                "pid": pid.toString()
            }
            reply_json["rid"] = whereStr.pid + '0' + nanoid(4)
            // let result = await dbo.collection("posts").updateOne(whereStr, { $addToSet: { "replys": reply_json } })
        } else if (Math.floor(redis_res.reply / reply_per_page) >= redis_res.page) {
            table = "reply"
            const result = await dbo.collection("reply").insertOne({
                "pid": pid.toString(),
                "reply_page_id": pid.toString() + (Math.floor(redis_res.page + 1)).toString(),
                "replys": [],
            })
            if (result.insertedCount) {
                await redis_client2.hincrby(pid, "page", 1)
            }
            whereStr = {
                "reply_page_id": pid.toString() + (Math.floor(redis_res.page + 1)).toString()
            }
            reply_json["rid"] = whereStr.reply_page_id + nanoid(4)
            // result = await dbo.collection("reply").updateOne(whereStr, { $addToSet: { "replys": reply_json } })
        } else {
            table = "reply"
            whereStr = {
                "reply_page_id": pid.toString() + redis_res.page.toString()
            }
            reply_json["rid"] = whereStr.reply_page_id + nanoid(4)
            // let result = await dbo.collection("reply").updateOne(whereStr, { $addToSet: { "replys": reply_json } })
        }
        // console.log(whereStr)
        // console.log(reply_json)
        const result = await dbo.collection(table).updateOne(whereStr, { $addToSet: { "replys": reply_json } })

        //mongodb
        //return res.json(result)
        if (result.modifiedCount) {
            await redis_client2.hincrby(pid, "reply", 1)
            return { "status": 20000 }
        } else {
            return { "status": 40000, "info": JSON.stringify(result) }
        }
    }

}
